import win32service
import win32serviceutil


# 运行方式一：使用管理员权限运行cmd/powershell，进入文件所在目录，执行命令 python 文件.py 运行
# 运行方式二：使用管理员的方式运行PyCharm,然后通过PyCharm运行文件


# 获取指定服务的状态
def get_service_status(service_name):
    try:
        # 打开服务控制管理器以枚举服务
        scm_handle = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ENUMERATE_SERVICE)
        # 打开指定的服务
        service_handle = win32service.OpenService(scm_handle, service_name, win32service.SERVICE_QUERY_STATUS)
        # 查询服务状态
        status = win32service.QueryServiceStatus(service_handle)[1]
        # 关闭服务句柄和服务控制管理器句柄
        win32service.CloseServiceHandle(service_handle)
        win32service.CloseServiceHandle(scm_handle)
        # 根据状态码返回相应的状态字符串
        if status == win32service.SERVICE_RUNNING:
            return '开启'
        elif status == win32service.SERVICE_STOPPED:
            return '关闭'
        else:
            return '未知状态'
    except Exception as e:
        print(f"获取服务状态失败: {e}")
        return None


# 根据查询字符串列出匹配的服务。
def list_services(query):
    services = []
    try:
        # 打开服务控制管理器以枚举服务
        scm_handle = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_ENUMERATE_SERVICE)
        # 定义服务类型和状态过滤器
        type_filter = win32service.SERVICE_WIN32
        state_filter = win32service.SERVICE_STATE_ALL
        # 枚举所有服务
        status_enum = win32service.EnumServicesStatus(scm_handle, type_filter, state_filter)
        for service_tuple in status_enum:
            service_name = service_tuple[0]
            if query.lower() in service_name.lower():
                # 获取服务状态并添加到服务列表中
                status = get_service_status(service_name)
                services.append((service_name, status))
        # 关闭服务控制管理器句柄
        win32service.CloseServiceHandle(scm_handle)
    except Exception as e:
        print(f"查询服务失败: {e}")
    return services


# 显示服务列表，每行显示5个服务。
def display_services(services):
    for i, (name, status) in enumerate(services, start=1):
        print(f"{i}: {name}-{status}", end="\t")
        if i % 5 == 0:
            print()
    print()


# 管理服务：查询、选择和操作服务。
def manage_services():
    while True:
        print("-----------------------------------------管理服务------------------------------------------")
        query = input("请输入要查询的服务名: ")
        services = list_services(query)
        if not services:
            print("未找到相关服务,请重新输入。")
            continue

        # 将服务列表以每行5个的方式显示出来
        display_services(services)

        try:
            choice = int(input("\n请输入要操作的服务编号: "))
            if choice < 1 or choice > len(services):
                raise ValueError
            selected_service, current_status = services[choice - 1]
        except ValueError:
            print("无效输入请重新输入。")
            continue
        print("---------------------------------------管理服务-操作----------------------------------------")
        print("1：开启服务             2：关闭服务             3：无操作")
        action = input("\n请选择操作：")
        if action == '1':
            if current_status == '开启':
                print(f"{selected_service}服务已开启!")
            else:
                try:
                    print(f"{selected_service}服务开启中...")
                    win32serviceutil.StartService(selected_service)
                    print(f"{selected_service}服务已开启")
                except Exception as e:
                    print(f"启动服务失败: {e}")
            break
        elif action == '2':
            if current_status == '关闭':
                print(f"{selected_service}服务已关闭")
            else:
                try:
                    print(f"{selected_service}服务关闭中...")
                    win32serviceutil.StopService(selected_service)
                    print(f"{selected_service}服务已关闭")
                except Exception as e:
                    print(f"停止服务失败: {e}")
            break
        elif action == '3':
            break
        else:
            print("无效输入请重新输入。")


# 查询常见的服务
def common_services_query():
    while True:
        print("\n-----------------------------------查询常见的服务-结果--------------------------------------")
        common_queries = ["mysql", "postgresql"]
        all_services = []
        for query in common_queries:
            all_services.extend(list_services(query))

        if not all_services:
            print("未找到常用服务。")
            return

        display_services(all_services)

        # 提供继续操作或退出的选择
        choice = input("是否继续操作：（1:继续操作   2:退出）")

        if choice == '2':
            break  # 回到主菜单

        elif choice == '1':
            try:
                service_choice = int(input("请输入要操作的服务编号: "))
                if service_choice < 1 or service_choice > len(all_services):
                    raise ValueError
                selected_service, current_status = all_services[service_choice - 1]
            except ValueError:
                print("无效输入请重新输入。")
                continue
            print("\n-----------------------------------查询常见的服务-操作--------------------------------------")
            print("1: 开启服务             2: 关闭服务             3: 无操作")
            action = input("\n请选择操作：")

            if action == '1':
                if current_status == '开启':
                    print(f"{selected_service}服务已开启!")
                else:
                    try:
                        print(f"{selected_service}服务开启中...")
                        win32serviceutil.StartService(selected_service)
                        print(f"{selected_service}服务已开启")
                    except Exception as e:
                        print(f"启动服务失败: {e}")
                break
            elif action == '2':
                if current_status == '关闭':
                    print(f"{selected_service}服务已关闭")
                else:
                    try:
                        print(f"{selected_service}服务关闭中...")
                        win32serviceutil.StopService(selected_service)
                        print(f"{selected_service}服务已关闭")
                    except Exception as e:
                        print(f"停止服务失败: {e}")
                break
            elif action == '3':
                continue  # 回到查询常见服务菜单

            else:
                print("无效输入请重新输入。")
        else:
            print("无效输入请重新输入。")


# 显示主菜单并处理用户输入。
def main_menu():
    while True:
        print("------------------------------------------主菜单------------------------------------------")
        print("|                                                                                       |")
        print("|  （0）退出                           （1）管理服务                      （2）常用服务查询    |")
        print("|                                                                                       |")
        print("-----------------------------------------------------------------------------------------")
        choice = input("请输入: ")
        if choice == '0':
            print("退出脚本")
            break
        elif choice == '1':
            manage_services()
        elif choice == '2':
            common_services_query()
        else:
            print("无效输入请重新输入。")


if __name__ == "__main__":
    main_menu()